﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Excel = Microsoft.Office.Interop.Excel;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.Security.Cryptography;
using psafth.FSR.Lapcounter.UserControls;

namespace psafth.FSR.Lapcounter
{
    public partial class ManageEventsUC : UserControl
    {
        private DbEntities _db;
        private List<Event> _events = new List<Event>();

        public ManageEventsUC()
        {
            InitializeComponent();
            _db = new DbEntities();

            UpdateHeatsPanel();
        }

        private void UpdateHeatsPanel()
        {
            foreach (var grouped in _db.HeatSet.GroupBy(s => new { s.RaceDate, s.Location }).Select(g => g))
            {
                var even = grouped.First();

                Event e = new Event(even.EventName, even.RaceDate, even.Organizer, even.Location, new List<Heat>());
                foreach (var heat in grouped)
                {
                    e.Heats.Add(heat);
                }

                _events.Add(e);
            }

            int nextYPos = 20;

            foreach (Event e in _events)
            {
                DisplayEventControl eventControl = new DisplayEventControl(e);

                eventControl.Location = new Point(20, nextYPos);

                tabPage1.Controls.Add(eventControl);

                nextYPos = eventControl.Location.Y + eventControl.Height + 20;
            }
        }

        void b_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        
        private List<HeatDriver> GetHeatDrivers(Excel.Worksheet sheet)
        {
            List<HeatDriver> heatDrivers = new List<HeatDriver>();

            Microsoft.Office.Interop.Excel.Range eventRange = sheet.UsedRange;

            for (int i = 7; i <= eventRange.Rows.Count; i++)
            {
                HeatDriver h = new HeatDriver();

                h.AverageLapTime = "0";
                h.BestLapTime = "0";

                string licenceNo = eventRange.Cells[i, 3].Text;
                string transponderId = eventRange.Cells[i, 4].Text;

                if (!string.IsNullOrWhiteSpace(licenceNo) && !string.IsNullOrWhiteSpace(transponderId))
                {

                    foreach (Driver d in _db.Drivers)
                    {
                        if (d.LicenceNumber == licenceNo.Trim().ToUpper())
                        {
                            h.Driver = d;
                            break;
                        }
                    }

                    if (h.Driver == null)
                        throw new Exception(string.Format("Driver {0} was not found in the database", licenceNo));

                    h.PreferredTransponder = transponderId.Trim();

                    heatDrivers.Add(h);
                }
            }
            return heatDrivers;
        }


        private void button1_Click(object sender, EventArgs e)
        {
            var fileDialog = new System.Windows.Forms.OpenFileDialog();
            if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string fileToOpen = fileDialog.FileName;

                Excel.Application xlApp = new Excel.Application();

                Excel.Workbook workBook = xlApp.Workbooks.Open(fileDialog.FileName);
                Excel._Worksheet eventWorksheet = workBook.Sheets[1];

                Excel.Range eventRange = eventWorksheet.UsedRange;

                string eventFullname = eventRange.Cells[2, 2].Text;
                string eventShortname = eventRange.Cells[3, 2].Text;
                string eventOrganizer = eventRange.Cells[4, 2].Text;
                string eventLocation = eventRange.Cells[5, 2].Text;
                string eventDateString = eventRange.Cells[6, 2].Text;
                
                DateTime eventDate = new DateTime();

                DateTime.TryParse(eventDateString, out eventDate);

                // For each heatsheet. Create heat(s).
                for (int i = 2; i <= workBook.Sheets.Count; i++)
                {
                    if (workBook.Sheets[i].Visible < 0)
                    {
                        Excel.Worksheet currentWorksheet = workBook.Sheets[i];

                        List<HeatDriver> registeredDrivers = GetHeatDrivers(currentWorksheet);
                        decimal totalNumberOfDrivers = registeredDrivers.Count;
                        decimal maxNumbPerheat = 12;

                        decimal modulo = totalNumberOfDrivers % maxNumbPerheat;

                        decimal highestNumberInLastHeat = 6;

                        if (modulo > 0)
                        {

                            for (int t = 12; t >= 4; t--)
                            {
                                decimal mod = totalNumberOfDrivers % t;

                                if (mod > highestNumberInLastHeat)
                                {
                                    highestNumberInLastHeat = mod;
                                    maxNumbPerheat = t;
                                }
                            }
                        }

                        decimal numberOfGroups = Math.Ceiling(totalNumberOfDrivers / maxNumbPerheat);
                        decimal numberPerGroup = Math.Floor(totalNumberOfDrivers / numberOfGroups);

                        if (currentWorksheet.UsedRange.Cells[4, 2].Text == "Slumpmässig")
                            registeredDrivers = new List<HeatDriver>(ShuffleDrivers(registeredDrivers));
                            
                        int regIndex = 0;

                        int numberOfHeatsPerGroup = Convert.ToInt32(currentWorksheet.Cells[3, 2].Text);

                        for (int k = 0; k < numberOfGroups * numberOfHeatsPerGroup; k++)
                        {
                            List<HeatDriver> heatDrivers = new List<HeatDriver>();

                            for (int j = 0; j <= numberPerGroup; j++)
                            {
                                heatDrivers.Add(registeredDrivers[regIndex]);
                                regIndex++;

                                if (regIndex == totalNumberOfDrivers)
                                {
                                    regIndex = 0;
                                    break;
                                }

                            }

                            string heatName = string.Format("Heat {0}",k+1);

                            Heat h = new Heat(heatDrivers, workBook.Sheets[i], eventDate, eventShortname, eventFullname, eventLocation, eventOrganizer, _db, heatName);

                            if (h.HeatDrivers.Count > 0 && h.HeatDuration > 0)
                            _db.HeatSet.Add(h);

                        }
                    }
                }

                try
                {

                    _db.SaveChanges();

                }
                catch (DbEntityValidationException dbEx)
                {
                    foreach (var validationErrors in dbEx.EntityValidationErrors)
                    {
                        foreach (var validationError in validationErrors.ValidationErrors)
                        {
                            Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                        }
                    }
                }
                UpdateHeatsPanel();
            }
        }

        private IEnumerable<HeatDriver> ShuffleDrivers(List<HeatDriver> list)
        {
            RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
            int n = list.Count;
            while (n > 1)
            {
                byte[] box = new byte[1];
                do provider.GetBytes(box);
                while (!(box[0] < n * (Byte.MaxValue / n)));
                int k = (box[0] % n);
                n--;
                HeatDriver value = list[k];
                list[k] = list[n];
                list[n] = value;
            }


            return list;
        }
    }
}


 //public Heat(List<HeatDriver> drivers, Microsoft.Office.Interop.Excel.Worksheet eventWorksheet, DateTime eventDate, string eventShortname, DbEntities _db, string heatName)
 //       {
 //           Microsoft.Office.Interop.Excel.Range eventRange = eventWorksheet.UsedRange;
 //           this.DisplayTitle = string.Format("{0} - {1} {2}", eventShortname, eventWorksheet.Name, heatName);

 //           this.HeatDuration = int.Parse(eventRange.Cells[2, 2].Text);

 //           this.RaceDate = eventDate;

 //           this.HeatDrivers = new List<HeatDriver>();

 //           for (int i = 7; i <= eventRange.Rows.Count; i++)
 //           {
 //               HeatDriver h = new HeatDriver();

 //               h.AverageLapTime = "0";
 //               h.BestLapTime = "0";
 //               h.StartNumber = i - 6;
                
 //               string licenceNo = eventRange.Cells[i, 3].Text;
 //               string transponderId = eventRange.Cells[i, 4].Text;

 //               foreach (Driver d in _db.Drivers)
 //               {
 //                   if (d.LicenceNumber == licenceNo.Trim())
 //                   {
 //                       h.Driver = d;
 //                       break;
 //                   }
 //               }

 //               if (h.Driver == null)
 //                   throw new Exception(string.Format("Driver {0} was not found in the database", licenceNo));

 //               h.PreferredTransponder = transponderId.Trim();

 //               this.HeatDrivers.Add(h);
 //           }
 //       }
